﻿using System;
using System.Linq;
using System.Xml.Linq;
using Wombat.Common;
using Wombat.Data.Model.Dtos;

namespace Wombat.Data.Model.Factories
{
    public class TagFactory : ITagFactory
    {
        private static class XmlItems
        {
            public static readonly XName ExtendedProperties = "ExtendedProperties";
            public static readonly XName Code = "Code";
            public static readonly XName In = "In";
            public static readonly XName Variable = "Variable";
            public static readonly XName TagId = "TagId";
        }

        public CodeTagDto CreateCodeTag(Tag tag)
        {
            var rv = new CodeTagDto();
            var tagXml = XElement.Parse(tag.ParameterSchema);
            if (tagXml == null)
                throw new InvalidOperationException(string.Format("Invalid tagDto extended property for tagDto '{0}': {1}", tag.Id, tag.ParameterSchema));
            rv.Code = tagXml.Element(XmlItems.Code).NullSafe(e => e.Value);
            rv.InputParameters = tagXml.Elements(XmlItems.In)
                                       .Select(e => new CodeTagAssignment { VariableName = (string)e.Attribute(XmlItems.Variable), 
                                           TagGuid = Guid.Parse((string)e.Attribute(XmlItems.TagId))});
            rv.Guid = tag.Guid;
            rv.Name = tag.Name;
            rv.Id = tag.Id;
            rv.Unit = tag.Unit.Name;
            rv.UnitId = tag.Unit.Id;
            return rv;
        }

        public Tag CreateTag(CodeTagDto codeTagDto)
        {
            var tagXml = new XElement(XmlItems.ExtendedProperties);
            tagXml.Add(new XElement(XmlItems.Code, new XCData(codeTagDto.Code)));
            foreach (var inputParameter in codeTagDto.InputParameters)
            {
                var inPar = new XElement(XmlItems.In);
                inPar.Add(new XAttribute(XmlItems.Variable, inputParameter.VariableName));
                inPar.Add(new XAttribute(XmlItems.TagId, inputParameter.TagGuid.ToString()));
                tagXml.Add(inPar);
            }
            return new Tag
                       {
                           Id = codeTagDto.Id,
                           Guid = codeTagDto.Guid,
                           Name = codeTagDto.Name,
                           Type = (int) TagType.Code,
                           UnitId = codeTagDto.UnitId,
                           ParameterSchema = tagXml.ToString()
                       };
            
        }
    }
}